#ifndef __FORMAT_REC__
#define __FORMAT_REC__

#include "../../interface/fmtid.h"

namespace xm
{
	typedef void (*DiscernHandler)( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt );

	void DiscernWinPE	( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt );
	void DiscernSWx		( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt );
	void DiscernDOC		( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt );
	void DiscernTIFF	( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt );
	void DiscernPDF		( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt );
	void DiscernDEX		( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt );
	void DiscernELF		( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt );
	void DiscernXDP		( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt );

	class KFormats : public IKFormats, UnkBase
	{
	protected:

		typedef struct fmt_pair
		{
			FileType		fmtid;
			xv::xvalue_t	addv;
		} fmtxv_t;

		typedef std::vector<fmt_pair>	formats_t;

		formats_t		_formats;

	public:

		UNKNOWN_IMP1(IKFormats);
		DEFAULT_INIT_CLASS();

		STDMETHOD(Push)( FileType type, xv::AnyValue * addv = 0 )
		{
			if( type == FMT_NONE ) 
				return E_INVALIDARG;
			fmtxv_t tmp;
			tmp.fmtid = type;
			if( addv ) tmp.addv = *addv;
			_formats.push_back( tmp );
			return S_OK;
		}

		STDMETHOD_(FileType,Find)( FileType type, xv::AnyValue * pval = 0 )
		{
			if( type == FMT_NONE ) return FMT_NONE;
			size_t c = _formats.size();
			for( size_t i = 0 ; i < c; ++ i )
			{
				if( _formats[i].fmtid != type )
					continue;

				if( pval ) _formats[i].addv.get( *pval );
				return _formats[i].fmtid;
			}
			return FMT_NONE;
		}

		// newType == FMT_NONE, remove oldType
		STDMETHOD(Replace)( FileType oldType, FileType newType, xv::AnyValue * addv = 0 )
		{
			size_t c = _formats.size();
			for( size_t i = 0 ; i < c; ++ i )
			{
				if( _formats[i].fmtid == oldType )
				{
					if( newType == FMT_NONE )
					{
						_formats.erase( _formats.begin() + i );
						return S_OK;
					}
					else
					{
						_formats[i].fmtid = newType;
						_formats[i].addv.clear();
						if( addv ) _formats[i].addv = *addv;
						return S_OK;
					}
				}
			}
			return Push( newType, addv );
		}

		STDMETHOD_(FileType,GetAt)( SIZE_T i, xv::AnyValue * pval = 0 )
		{
			if( i >= _formats.size() ) return FMT_NONE;
			if( pval ) _formats[i].addv.get( *pval );
			return _formats[i].fmtid;
		}

		STDMETHOD_(SIZE_T,Count)()
		{
			return _formats.size();
		}

		STDMETHOD(Clear)()
		{
			_formats.clear();
			return S_OK;
		}
	};








};

#endif